﻿using DictinaryTools.DictinaryTools;
using SqlSugar;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace DictinaryTools
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.progressBar1.Hide();
        }
        SqlSugarClient db = null;
        List<string> tableList = new List<string>();
        /// <summary>
        /// 连接数据库
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button1_Click(object sender, EventArgs e)
        {
            try
            {
                //创建数据库对象
                db = new SqlSugarClient(new ConnectionConfig()
                {
                    ConnectionString = textBox1.Text.Trim(),//连接符字串
                    DbType = SqlSugar.DbType.SqlServer,
                    IsAutoCloseConnection = true
                });

                if (db != null)
                {
                    ConnectStatus.Text = "已连接数据库";
                }
                var TableList = db.Ado.GetDataTable(@" select * from (select top 100000000 ROW_NUMBER() OVER(ORDER BY m.name) as '序号',m.name as '表名',
(SELECT isnull(A.value,'')as value FROM sys.extended_properties A
LEFT JOIN sys.columns B ON A.major_id=B.object_id AND A.minor_id=B.column_id
LEFT JOIN sys.tables C ON A.major_id=C.object_id
WHERE A.class=1 AND C.name=m.name and isnull(B.name,'')='') as '表说明'
FROM sysobjects AS m
WHERE (m.type = 'u')
ORDER BY m.name)A");

                //为dgv增加复选框列
                DataGridViewCheckBoxColumn checkbox = new DataGridViewCheckBoxColumn();
                //列显示名称
                checkbox.HeaderText = "选择";
                checkbox.Name = "IsChecked";
                checkbox.TrueValue = true;
                checkbox.FalseValue = false;
                checkbox.DataPropertyName = "IsChecked";
                //列宽
                checkbox.Width = 50;
                //列大小不改变
                checkbox.Resizable = DataGridViewTriState.False;
                //添加的checkbox在dgv第一列
                this.dgv.Columns.Insert(0, checkbox);
                dgv.DataSource = TableList;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

        /// <summary>
        /// 控制checkbox勾选还是不勾选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void dgv_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            //不是序号列和标题列时才执行
            if (e.RowIndex != -1 && e.ColumnIndex != -1)
            {
                //checkbox 勾上
                if ((bool)dgv.Rows[e.RowIndex].Cells[0].EditedFormattedValue == true)
                {
                    //选中改为不选中
                    this.dgv.Rows[e.RowIndex].Cells[0].Value = false;
                }
                else
                {
                    //不选中改为选中
                    this.dgv.Rows[e.RowIndex].Cells[0].Value = true;
                }
            }
        }

        /// <summary>
        /// 全选
        /// </summary>
        private void SelectAll()
        {
            //结束列表的编辑状态,否则可能无法改变CheckBox的状态
            dgv.EndEdit();
            for (var i = 0; i < dgv.Rows.Count; i++)
            {
                dgv.Rows[i].Cells[0].Value = true;//设置为选中状态
            }
        }
        /// <summary>
        /// 取消全选
        /// </summary>
        private void UnSelectAll()
        {
            //结束列表的编辑状态,否则可能无法改变CheckBox的状态
            dgv.EndEdit();
            for (var i = 0; i < dgv.Rows.Count; i++)
            {
                dgv.Rows[i].Cells[0].Value = false;//设置为取消选中状态
            }
        }

        private void checkBox1_Click(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                SelectAll();
            }
            else
            {
                UnSelectAll();
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            string path=FolderDialog("");
            textBox2.Text = path;
        }

        private string FolderDialog(string name)
        {
            string FolderPath = name;
            FolderBrowserDialog dialog = new FolderBrowserDialog();
            dialog.Description = "选择目录";
            if (dialog.ShowDialog() == DialogResult.OK)
            {
                //获取选择的目录路径
                FolderPath = dialog.SelectedPath;
            }
            return FolderPath;
        }

        /// <summary>
        /// 生成数据字典
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button2_Click(object sender, EventArgs e)
        {
            if (textBox2.Text=="")
            {
                MessageBox.Show("请选择生成目录", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            if (db == null)
            {
                MessageBox.Show("当前还未连接数据库", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }
            else
            {
                for (int i = 0; i < dgv.Rows.Count; i++)
                {
                    if ((bool)dgv.Rows[i].Cells[0].EditedFormattedValue == true && dgv.Rows[i].Cells[2].Value!=null)
                    {
                        //获取当前行的第一个单元格 + @ +第二个单元格的内容
                        tableList.Add(dgv.Rows[i].Cells[2].Value.ToString());
                    }

                }
                if (tableList.Count == 0)
                {
                    MessageBox.Show("还未选择任何数据", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
                else
                {
                    this.progressBar1.Show();
                    button2.Enabled = false;
                    ThreadMethod method = new ThreadMethod();
                    //先订阅一下事件
                    method.threadStartEvent += new EventHandler(method_threadStartEvent);
                    method.threadEvent += new EventHandler(method_threadEvent);
                    method.threadEndEvent += new EventHandler(method_threadEndEvent);
                    Task task = new Task(() => { method.runMethod(tableList,db,textBox2.Text); });
                    task.Start();
                }
            }
        }

        public void DoWithProcess(Action<int> percent)
        {
            Thread.Sleep(50);
            List<DataTable> tbList = new List<DataTable>();
           for (int i = 0; i <tableList.Count; i++)
           {
                #region 获取表结构
                var dataList = db.Ado.GetDataTable(string.Format(@"SELECT
    表名=case   when   a.colorder=1   then   d.name   else   ''   end,
    表说明=case   when   a.colorder=1   then   isnull(f.value,'')   else   ''   end,
    字段序号=a.colorder,
    字段名=a.name,
    标识=case   when   COLUMNPROPERTY(   a.id,a.name,'IsIdentity')=1   then   '√'else   ''   end,
    主键=case   when   exists(SELECT   1   FROM   sysobjects   where   xtype='PK'   and   name   in   (
        SELECT   name   FROM   sysindexes   WHERE   indid   in(
            SELECT   indid   FROM   sysindexkeys   WHERE   id   =   a.id   AND   colid=a.colid
        )))   then   '√'   else   ''   end,
    类型=b.name,
    占用字节数=a.length,
    长度=COLUMNPROPERTY(a.id,a.name,'PRECISION'),
    小数位数=isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0),
    允许空=case   when   a.isnullable=1   then   '√'else   ''   end,
    默认值=isnull(e.text,''),
    字段说明=isnull(g.[value],'')
FROM   syscolumns   a
    left join   systypes   b   on   a.xusertype=b.xusertype
    inner join   sysobjects   d   on   a.id=d.id     and   d.xtype='U'   and     d.name<>'dtproperties'
    left join   syscomments   e   on   a.cdefault=e.id
    left join   sys.extended_properties   g   on   a.id=g.major_id   and   a.colid=g.minor_id
    left join   sys.extended_properties   f   on   d.id=f.major_id   and   f.minor_id=0
where d.name='{0}'         --如果只查询指定表,加上此条件
order by a.id,a.colorder", tableList[i]));
                #endregion

                tbList.Add(dataList);
                percent(i);
            }
        }
        void process_BackgroundWorkerCompleted(object sender, BackgroundWorkerEventArgs e)
        {
            if (e.BackGroundException == null)
            {
                MessageBox.Show("执行完毕");
            }
            else
            {
                MessageBox.Show("异常:" + e.BackGroundException.Message);
            }
        }

        private void dgv_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
        {
            string TableName=dgv.Rows[e.RowIndex].Cells[2].Value.ToString();
            #region 获取表结构
            var dataList = db.Ado.GetDataTable(string.Format(@"SELECT
    表名=case   when   a.colorder=1   then   d.name   else   ''   end,
    表说明=case   when   a.colorder=1   then   isnull(f.value,'')   else   ''   end,
    字段序号=a.colorder,
    字段名=a.name,
    标识=case   when   COLUMNPROPERTY(   a.id,a.name,'IsIdentity')=1   then   '√'else   ''   end,
    主键=case   when   exists(SELECT   1   FROM   sysobjects   where   xtype='PK'   and   name   in   (
        SELECT   name   FROM   sysindexes   WHERE   indid   in(
            SELECT   indid   FROM   sysindexkeys   WHERE   id   =   a.id   AND   colid=a.colid
        )))   then   '√'   else   ''   end,
    类型=b.name,
    占用字节数=a.length,
    长度=COLUMNPROPERTY(a.id,a.name,'PRECISION'),
    小数位数=isnull(COLUMNPROPERTY(a.id,a.name,'Scale'),0),
    允许空=case   when   a.isnullable=1   then   '√'else   ''   end,
    默认值=isnull(e.text,''),
    字段说明=isnull(g.[value],'')
FROM   syscolumns   a
    left join   systypes   b   on   a.xusertype=b.xusertype
    inner join   sysobjects   d   on   a.id=d.id     and   d.xtype='U'   and     d.name<>'dtproperties'
    left join   syscomments   e   on   a.cdefault=e.id
    left join   sys.extended_properties   g   on   a.id=g.major_id   and   a.colid=g.minor_id
    left join   sys.extended_properties   f   on   d.id=f.major_id   and   f.minor_id=0
where d.name='{0}'         --如果只查询指定表,加上此条件
order by a.id,a.colorder", TableName));


            #endregion
            
            TableStructInfo info = new TableStructInfo();
            this.AddOwnedForm(info);
            info.showdata(dataList, TableName);
            info.Show();
        }

        /// <summary>
        /// 线程开始事件,设置进度条最大值
        /// 但是我不能直接操作进度条,需要一个委托来替我完成
        /// </summary>
        /// <param name="sender">ThreadMethod函数中传过来的最大值</param>
        /// <param name="e"></param>
        void method_threadStartEvent(object sender, EventArgs e)
        {
            int maxValue = Convert.ToInt32(sender);
            this.Invoke(new Action<int>(setMax), maxValue);
        }
        /// <summary>
        /// 线程执行中的事件,设置进度条当前进度
        /// 但是我不能直接操作进度条,需要一个委托来替我完成
        /// </summary>
        /// <param name="sender">ThreadMethod函数中传过来的当前值</param>
        /// <param name="e"></param>
        void method_threadEvent(object sender, EventArgs e)
        {
            int nowValue = Convert.ToInt32(sender);
            this.Invoke(new Action<int>(setNow), nowValue);
        }
        /// <summary>
        /// 线程完成事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void method_threadEndEvent(object sender, EventArgs e)
        {

            MessageBox.Show("执行已经完成!");
            this.Invoke(new Action(setButton));

            //只有入参用Action ,如果有返回值用FunC
        }

        public void setButton()
        {
            this.button2.Enabled = true;
            this.progressBar1.Hide();
        }

        /// <summary>
        /// 我被委托调用,专门设置进度条最大值的
        /// </summary>
        /// <param name="maxValue"></param>
        public void setMax(int maxValue)
        {
            this.progressBar1.Maximum = maxValue;

        }

        /// <summary>
        /// 我被委托调用,专门设置进度条当前值的
        /// </summary>
        /// <param name="nowValue"></param>
        private void setNow(int nowValue)
        {
            this.progressBar1.Value = nowValue;
        }
    }
}
